#ifndef DIARYTOOL_SQL_SQL_DRIVER_HPP
#define DIARYTOOL_SQL_SQL_DRIVER_HPP

#include "config.h"
#include "sql/types.hpp"
#include <vector>

struct CfgItemBase;

// 数据库更新信息
struct UpgradeInfo {
    int32_t version_from;
    int32_t version_to;
    std::vector<const char*> statements;
};

class DIARY_APP_SDK_API ISqlDriver {
public:
    virtual ~ISqlDriver();

    /**
     * @brief 初始化数据库连接
     */
    virtual void InitConnection() = 0;

    /**
     * @brief 查询数据是否已经配置过
     * @return true => 已经配置过; false => 尚未配置
     */
    virtual bool IsConfigured() = 0;

    /**
     * @brief 初始化数据库，实现创建表的操作
     */
    virtual void InitTables() const = 0;

    /**
     * @brief 初始化预执行语句，没有可以写空函数体
     */
    virtual void InitPreparedStatements() const = 0;

    /**
     * @brief 连接保活
     */
    virtual bool KeepAlive() = 0;

    // 获取所有可用的标签信息
    virtual std::vector<Tag> AllTags() const = 0;
    // 添加一个标签
    virtual Tag NewTag(const std::string& tag_name, uint32_t color, uint32_t level) const = 0;
    // 删除一个标签
    virtual bool DeleteTag(int tag_id) const = 0;
    // 更新标签的属性
    virtual bool UpdateTag(Tag& tag) const = 0;

    // 获取redmine活动列表
    virtual std::vector<RedMineActivity> AllRedMineActivities() const = 0;
    // 删除一个redmine活动
    virtual bool DeleteRedMineActivity(int act_id) const = 0;
    // 更新redmine活动
    virtual bool UpdateRedMineActivity(RedMineActivity& tag) const = 0;

    // 获取redmine问题列表
    virtual std::vector<RedMineIssue> AllRedMineIssues() const = 0;
    // 删除一个redmine问题
    virtual bool DeleteRedMineIssue(int issue_id) const = 0;
    // 更新redmine问题
    virtual bool UpdateRedMineIssue(RedMineIssue& tag) const = 0;

    // 新建一个工作项
    virtual WorkItem NewWorkItem(double hour, const std::string& comment, const std::string& note, const std::string& create_date, int32_t priority = 0) const = 0;
    // 更新工作项的关联活动
    virtual bool SetWorkItemActivity(int work_id, int act_id) const = 0;
    // 更新工作项的关联问题
    virtual bool SetWorkItemIssue(int work_id, int issue_id) const = 0;
    // 将工作项标记为已提交
    virtual bool SetWorkItemUploaded(int work_id) const = 0;
    // 更新工作项的属性（可更新属性为标题、耗时、日期、备注）
    virtual bool UpdateWorkItem(WorkItem& tag) const = 0;
    // 删除工作项
    virtual bool DeleteWorkItem(int work_id) const = 0;

    // 为工作项添加一个标签
    virtual bool AddItemTag(int work_id, int tag_id) const = 0;
    // 删除工作项的标签
    virtual bool DeleteItemTag(int work_id, int tag_id) const = 0;
    // 清除工作项的所有标签
    virtual bool ClearItemTags(int work_id) const = 0;
    // 获取特定工作项的所有标签
    virtual std::vector<Tag> AllWorkItemTags(int work_id) = 0;

    // 获取年份列表
    virtual std::vector<std::string> GetYearList() const = 0;
    // 获取特定年份下的月份列表
    virtual std::vector<std::string> GetMonthList(const std::string& year) const = 0;
    // 根据年和月获取日期列表
    virtual std::vector<std::string> GetDayList(const std::string& year_and_month) const = 0;
    // 获取某特定日期下的所有工作项
    virtual std::vector<WorkItem> GetDailyItems(const std::string& date) const = 0;
    // 获取一定时间范围内的工作项，并且工作项具有所给的标签
    virtual std::vector<WorkItem> GetItemsByTagAndDate(const std::string& date_start, const std::string& date_end, int tag_id_l1, int tag_id_l2) const = 0;

    // 新建任务，任务描述需要唯一
    virtual WorkTask NewTask(std::string task_desc, const std::string &create_date, uint32_t color = 0xffffffff) = 0;
    // 更新任务属性（可更改属性为redmine关联任务和redmine关联活动、标签列表、颜色）
    virtual bool UpdateTask(const WorkTask& task) = 0;
    // 删除任务
    virtual bool DeleteTask(const WorkTask& task) = 0;
    // 设置任务状态
    virtual bool SetTaskStatus(WorkTask& task, TaskStatus status) = 0;
    // 获取所有任务
    virtual std::vector<WorkTask> GetTasks() const = 0;
    // 获取正在进行的任务
    virtual WorkTask GetCurrentTask() const = 0;
    // 清除正在执行的任务标记
    virtual void ClearActiveTask() const = 0;


    // 添加耗时信息项
    virtual TimeEntry NewTimeEntry(int32_t task_id, const std::string& start_date_time) = 0;
    // 更新耗时信息项，只会计算耗时信息
    virtual bool UpdateTimeEntry(TimeEntry& entry, const std::string &end_time, int32_t duration) = 0;
    // 获取正在统计的耗时项
    virtual TimeEntry GetCurrentTimeEntry(int32_t entry_id) const = 0;
    // 将所给耗时信息标记为已导出
    virtual void MarkTimeEntryAsExported(TimeEntry& entry) const = 0;

    // 获取所属任务在所给时间段的耗时信息
    virtual std::vector<TimeEntry> GetTimeEntries(int32_t task_id, const std::string& date_beg, const std::string& date_end) = 0;
    // 获取所有任务在所属时间段的耗时信息，不包含不完整的耗时信息
    virtual std::vector<TimeEntry> GetTimeEntries(const std::string& date_beg, const std::string& date_end) const = 0;

    // 获取日期范围内的统计信息
    virtual StatisticsResult GetStatisticsResult(const std::string& date_start, const std::string& date_end) const = 0;
    // 获取全部日期范围的统计信息
    virtual StatisticsResult GetStatisticsResult() const = 0;
    // 获取指定日期内的标签数据
    virtual StatisticsResult GetStatisticsResult(const std::string& date_start, const std::string& date_end, int tag_id) const = 0;

    // 获取数据库版本
    [[nodiscard]] virtual int32_t GetDataVersion() const = 0;
    // 数据库升级
    virtual void MigrateTables(int32_t old_version) const = 0;
    
    // 获取驱动配置
    virtual CfgItemBase* GetConfig() const;
};

/**
 * 动态数据库驱动需要动态加载，LoadLibrary / dlopen，入口函数名 GetDriverFactory
 */
using PFN_DynamicDriverCreate = ISqlDriver * (*)();

#pragma pack(push,1)
struct DriverFactory {
    const char* const       name;
    uint64_t          const version;    // 用来做版本兼容验证
    PFN_DynamicDriverCreate factory;    // 创建驱动实例的函数

    inline DriverFactory(const char* name, PFN_DynamicDriverCreate f) : name(name), version{ DATA_VERSION }, factory{ f } {}
};
#pragma pack(pop)
#define DYNAMIC_DRIVER_ENTRY_NAME "GetDriverFactory"
using PFN_DriverEntryPoint = const DriverFactory* (*)();

#endif // DIARYTOOL_SQL_SQL_DRIVER_HPP
